﻿using jvm.instructions.common;
using jvm.rtda;
using jvm.rtda.frame;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace jvm.instructions.stack
{
    class DUP : NoOperandsInstruction
    {
        public override void Execute(JFrame frame)
        {
            JOperandStack stack = frame.operandStack;
            Slot slot = stack.PopSlot();
            stack.PushSlot(slot);
            stack.PushSlot(slot);
        }
    }

    /*
    bottom -> top
    [...][c][b][a]
              __/
             |
             V
    [...][c][a][b][a]
    */
    class DUP_X1 : NoOperandsInstruction
    {
        public override void Execute(JFrame frame)
        {
            JOperandStack stack = frame.operandStack;
            Slot slot1 = stack.PopSlot();
            Slot slot2 = stack.PopSlot();
            stack.PushSlot(slot1);
            stack.PushSlot(slot2);
            stack.PushSlot(slot1);
        }
    }

    /*
    bottom -> top
    [...][c][b][a]
           _____/
          |
          V
    [...][a][c][b][a]
    */
    class DUP_X2 : NoOperandsInstruction
    {
        public override void Execute(JFrame frame)
        {
            JOperandStack stack = frame.operandStack;
            Slot slot1 = stack.PopSlot();
            Slot slot2 = stack.PopSlot();
            Slot slot3 = stack.PopSlot();
            stack.PushSlot(slot1);
            stack.PushSlot(slot3);
            stack.PushSlot(slot2);
            stack.PushSlot(slot1);
        }
    }

    class DUP2 : NoOperandsInstruction
    {
        public override void Execute(JFrame frame)
        {
            JOperandStack stack = frame.operandStack;
            Slot slot1 = stack.PopSlot();
            Slot slot2 = stack.PopSlot();
            stack.PushSlot(slot2);
            stack.PushSlot(slot1);
            stack.PushSlot(slot2);
            stack.PushSlot(slot1);
        }
    }

    /*
    bottom -> top
    [...][c][b][a]
           _/ __/
          |  |
          V  V
    [...][b][a][c][b][a]
    */
    class DUP2_X1 : NoOperandsInstruction
    {
        public override void Execute(JFrame frame)
        {
            JOperandStack stack = frame.operandStack;
            Slot slot1 = stack.PopSlot();
            Slot slot2 = stack.PopSlot();
            Slot slot3 = stack.PopSlot();
            stack.PushSlot(slot2);
            stack.PushSlot(slot1);
            stack.PushSlot(slot3);
            stack.PushSlot(slot2);
            stack.PushSlot(slot1);
        }
    }

    /*
    bottom -> top
    [...][d][c][b][a]
           ____/ __/
          |   __/
          V  V
    [...][b][a][d][c][b][a]
    */
    class DUP2_X2 : NoOperandsInstruction
    {
        public override void Execute(JFrame frame)
        {
            JOperandStack stack = frame.operandStack;
            Slot slot1 = stack.PopSlot();
            Slot slot2 = stack.PopSlot();
            Slot slot3 = stack.PopSlot();
            Slot slot4 = stack.PopSlot();
            stack.PushSlot(slot2);
            stack.PushSlot(slot1);
            stack.PushSlot(slot4);
            stack.PushSlot(slot3);
            stack.PushSlot(slot2);
            stack.PushSlot(slot1);
        }
    }
}
